import { AssetManager, assetManager, Prefab, SpriteAtlas, SpriteFrame } from "cc";
import { ViewId } from "../common/view/IView";
import { IMgr } from "./IMgr";



export class ResMgr implements IMgr {

    init() {

    }

    finit() {

    }

    getBundle(name: string): AssetManager.Bundle {
        return this._bundles.get(name);
    }

    private _bundles: Map<string, AssetManager.Bundle> = new Map();

    private _bundleMapViewId: Map<AssetManager.Bundle, Set<ViewId>> = new Map();

    get bundles(): Map<string, AssetManager.Bundle> {
        return this._bundles;
    }

    /**
     * 加载bundle
     * @param viewId 
     * @param name 
     * @returns 
     */
    async loadBundle(viewId: ViewId, name: string): Promise<AssetManager.Bundle> {
        const bundle = this._bundles.get(name);
        if (bundle) {
            return Promise.resolve(bundle);
        }
        return new Promise((resolve, reject) => {
            assetManager.loadBundle(name, (err, bundle) => {
                if (err) {
                    return reject(err);
                }

                /** */
                let set = this._bundleMapViewId.get(bundle);
                if (!set) {
                    set = this._bundleMapViewId.set(bundle, new Set()).get(bundle)
                }
                set.add(viewId);

                /** */
                this._bundles.set(name, bundle);

                resolve(bundle);
            });
        });
    }

    /**
     * 根据bundle名字释放bundle资源
     * @param bundleName 
     */
    releaseAllByBundle(bundleName: string): void {
        const bundle = this._bundles.get(bundleName);
        if(!bundle){
            return;
        }
        // this._bundleMapViewId.delete(bundle);
        // this.bundles.delete(bundleName);
        bundle.releaseAll();
    }

    /**
     * 加载散图
     * @param bundleName 
     * @param res 
     */
    async loadSinglePicResByBundle(bundleName: string, resName: string): Promise<SpriteFrame> {
        const bundle = this._bundles.get(bundleName);
        if (!bundle) {
            return Promise.reject(`bundle not found, bundle name .. ` + bundleName)
        }

        const res = bundle.get(resName) as SpriteFrame;
        if (res) {
            return Promise.resolve(res);
        }

        return new Promise((resolve, reject) => {
            bundle.load(resName, SpriteFrame, (err, data: SpriteFrame) => {
                if (err) {
                    return reject(err);
                }
                resolve(data);
            })
        })
    }

    /**
     * 加载图集
     * @param bundleName 
     * @param atlasPath 
     * @param type 
     */
    async loadAtlasByBundle(bundleName: string, atlasPath: string): Promise<SpriteAtlas> {
        const bundle = this._bundles.get(bundleName);
        if (!bundle) {
            return Promise.reject(`bundle not found, bundle name .. ` + bundleName)
        }
        if (!atlasPath) {
            return Promise.resolve(null)
        }

        const atlas = bundle.get(atlasPath) as SpriteAtlas;
        if (atlas) {
            return Promise.resolve(atlas);
        }

        return new Promise((resolve, reject) => {
            bundle.load(atlasPath, SpriteAtlas, (err, data: SpriteAtlas) => {
                if (err) {
                    return reject(err);
                }
                resolve(data);
            })
        })
    }

    async loadAtlasArrByBundle(bundleName: string, atlasNameArr: string[]): Promise<any> {
        const total = atlasNameArr.length;
        if (!total) {
            return Promise.resolve(null);
        }
        let count = 0;
        return new Promise((resolve, reject) => {
            for (const atlasName of atlasNameArr) {
                this.loadAtlasByBundle(bundleName, atlasName).then(() => {
                    count++;
                    if (count >= total) {
                        resolve(null);
                    }
                }).catch((reason) => {
                    reject(reason);
                })
            }
        })

    }

    /**
     * 加载预制体
     * @param bundleName 
     * @param prefabPath 
     * @returns 
     */
    async loadPrefab(bundleName: string, prefabPath: string): Promise<Prefab> {
        const bundle = this._bundles.get(bundleName);
        if (!bundle) {
            return Promise.reject(`bundle not found, bundle name .. ` + bundleName)
        }

        const res = bundle.get(prefabPath) as Prefab;
        if (res) {
            return Promise.resolve(res);
        }
        return new Promise((resolve, reject) => {
            bundle.load(prefabPath, (err, data: Prefab) => {
                if (err) {
                    return reject(err);
                }
                resolve(data);
            })
        })

    }

}